package br.com.gaspar.framework.persistencia.jpa;


import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import br.com.gaspar.framework.persistencia.IBaseDAO;
import br.com.gaspar.framework.persistencia.anotacao.ExclusaoLogica;
import br.com.gaspar.framework.persistencia.util.IJPAParams;
import br.com.gaspar.framework.persistencia.util.JPAUtil;
import br.com.gaspar.utils.AnotacaoUtil;
import br.com.gaspar.utils.ColecaoUtil;
import br.com.gaspar.utils.ReflexaoUtil;
import br.com.gaspar.utils.StringUtil;
import br.com.gaspar.utils.entidade.EntidadeBase;
import br.com.gaspar.utils.exception.BaseException;
/**
 * Classe abstrata que serve de implementação genérica para JPA.
 * @author gaspar
 *
 * @param <T>
 */
public abstract class BaseDAO<T extends EntidadeBase> implements IBaseDAO<T> {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1816981188404559265L;

	protected static Logger log = LoggerFactory.getLogger(BaseDAO.class);
	
	protected EntityManager entityManager;
	
	private Class<T> classePersistente;
	
	public BaseDAO(){
			/*classePersistente = (Class<T>) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0];*/
	}
	
	public BaseDAO(Class<T> classePersistente){
		this.classePersistente = classePersistente;
	}

	/**
	 * Método que deve ser implementado pelo EJB e anotado com @PersistenContext,
	 * ligando o entityManager injetado com o do SefazDAO
	 * 
	 * Ex:
	 * 		@PersistenceContext(unitName = "MinhaPersistentUnit")
		    @Override
		    protected void setEntityManager(EntityManager entityManager) {
		        this.entityManager = entityManager;
		    }
	 * @param entityManager
	 */
	protected abstract void setEntityManager(EntityManager entityManager);

	public EntityManager getEntityManager() {
		return entityManager;
	}
	
	public Class<T> getClassePersistente() {
		return classePersistente;
	}

	public void setClassePersistente(Class<T> classePersistente) {
		this.classePersistente = classePersistente;
	}
	
	/**
	 * grava objeto no banco de dados
	 * 
	 * @author gaspar
	 */
	@Override
	public T gravar(T entidade) throws BaseException {
		try{
			getEntityManager().persist(entidade);
			
			log.debug("Passou na gravação - SefazDAO");
		}catch(ConstraintViolationException e){
			log.error("Erro de constraint ao gravar!");
			throw e;
		}catch (Exception e) {
			log.error("Erro na gravação - SefazDAO");
			throw new BaseException(e, "sefaz.erro.persistencia.gravar");
		}
		return entidade;
	}
	
	/**
	 * Atualiza objeto no banco de dados
	 * 
	 * @author gaspar
	 */
	@Override
	public T editar(T entidade) throws BaseException {
		T atualizado = null;
		try{
			atualizado = getEntityManager().merge(entidade);
			
			log.debug("Passou na edição - SefazDAO");
		}catch (Exception e) {
			log.error("Erro na edição - SefazDAO", e);
			throw new BaseException(e, "sefaz.erro.persistencia.editar");
		}
		return atualizado;
	}

	/**
	 * Exclui objeto no banco de dados
	 * @param entidade
	 * @param id
	 * @throws BaseException
	 * 
	 * @author gaspar
	 */
	public void excluir(Class<T> entidade, Long id) throws BaseException {
		try{
			Object obj = buscarPorId(entidade, id);
			getEntityManager().remove(obj);
			getEntityManager().flush();
 
			log.debug("Passou na exclusão - SefazDAO");
		}catch (Exception e) {
			log.error("Erro na exclusão - SefazDAO");
			if(e.getCause() instanceof ConstraintViolationException){
				throw new BaseException(e, "Registro não pode ser excluído");
			}
			throw new BaseException(e, "sefaz.erro.persistencia.excluir");
		}
	}
	
	public void excluir(T entidade) throws BaseException {
		try{
			getEntityManager().refresh(entidade);
			getEntityManager().remove(entidade);
 
			log.debug("Passou na exclusão - SefazDAO");
		}catch (Exception e) {
			log.error("Erro na exclusão - SefazDAO");
			throw new BaseException(e, "sefaz.erro.persistencia.excluir");
		}
	}

	/**
	 * Recupera Objeto do banco através da chave primária
	 * 
	 * @author gaspar
	 */
	@Override
	public T buscarPorId(Class<T> clazz, Long id) throws BaseException {
		T objeto = null;
		try{
			objeto = getEntityManager().find(clazz, id);
			log.debug("Passou na buscaPorId - SefazDAO");
			
		}catch(NoResultException e){
			return null;
		}catch (Exception e) {
			log.error("Erro na buscaPorId - SefazDAO");
			throw new BaseException(e, "sefaz.erro.persistencia.buscarPorId");
		}
		return objeto;
	}
	
	public T buscarPorId(Long id) throws BaseException {
		T objeto = null;
		try{
			objeto = getEntityManager().find(classePersistente, id);
			log.debug("Passou na buscaPorId - SefazDAO");
			
		}catch(NoResultException e){
			return null;
		}catch (Exception e) {
			log.error("Erro na buscaPorId - SefazDAO");
			throw new BaseException(e, "sefaz.erro.persistencia.buscarPorId");
		}
		return objeto;
	}

	/**
	 * Recupera objeto do banco através da namedQuery declarada no objeto persistente
	 * 
	 * @param namedQuery - NamedQuery da entidade persistente
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public T buscarPorNamedQuery(String namedQuery, Object... params) throws BaseException {
		T objeto = null;
		try {
			Query query = getEntityManager().createNamedQuery(namedQuery);
			JPAUtil.setParameters(query, params);
			objeto = (T) query.getSingleResult();
			
		}catch (NoResultException e) {
			log.debug("Objeto não encontrado! - - SefazDAO");
			return null;
		} catch (Exception ex) {
	    	log.error("Erro ao buscarPorNamedQuery - SefazDAO : " + ex.getMessage());
	    	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
	    }
		return objeto;
	}
	
	/**
	 * Recupera objeto do banco através da namedQuery declarada no objeto persistente usando função HQL
	 * 
	 * @param namedQuery - NamedQuery da entidade persistente
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados
	 * 
	 * @author gaspar
	 */
	@Override
	public Object buscarPorNamedQuery2(String namedQuery, Object... params) throws BaseException {
		Object objeto = null;
		try {
			Query query = getEntityManager().createNamedQuery(namedQuery);
			JPAUtil.setParameters(query, params);
			objeto = query.getSingleResult();
			
		}catch (NoResultException e) {
			log.debug("Objeto não encontrado! - - SefazDAO");
			return null;
		} catch (Exception ex) {
	    	log.error("Erro ao buscarPorNamedQuery - SefazDAO : " + ex.getMessage());
	    	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
	    }
		return objeto;
	}
	
	/**
	 * Recupera objeto do banco usando sql nativo
	 * 
	 * @param classePersistente - Classe da entidade persistente.
	 * @param sql - sql que será executado contra o banco de dados.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public T buscarPorNativeQuery(Class<T> classePersistente, String sql, Object... params) throws BaseException {
		T objeto = null;
		try {
			Query query = getEntityManager().createNativeQuery(sql, classePersistente);
            JPAUtil.setParameters(query, params);
            objeto = (T) query.getSingleResult();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarPorNativeQuery - SefazDAO : " + ex.getMessage());
        	log.error("Entidade: "+ classePersistente.getName());
        	log.error("Sql: " + sql);
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return objeto;
	}
	
	/**
	 * Recupera objeto do banco através da sql nativa.
	 * 
	 * @param sql - SQL que será executado contra o banco de dados.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados.
	 * 
	 * @author gaspar
	 * 
	 */
	@SuppressWarnings("unchecked")
	public T buscarPorNativeQuery(String sql, Object... params) throws BaseException {
		T objeto = null;
		try {
			Query query = getEntityManager().createNativeQuery(sql);
            JPAUtil.setParameters(query, params);
            objeto = (T) query.getSingleResult();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarPorNativeQuery - SefazDAO : " + ex.getMessage());
        	log.error("Sql: " + sql);
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return objeto;
	}
	
	/**
	 * Busca usando native query retornando para um SQLResultSetMapping
	 * @param sql -SQL que será executado contra o banco de dados.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados.
	 * @param nomeResultSetMapping - nome do ResultSetMapping.
	 * @return
	 * @throws BaseException
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	public T buscarPorNativeQuery(String sql, String nomeResultSetMapping, Object... params) throws BaseException {
		T objeto = null;
		try {
			Query query = getEntityManager().createNativeQuery(sql, nomeResultSetMapping);
            JPAUtil.setParameters(query, params);
            objeto = (T) query.getSingleResult();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarPorNativeQuery - SefazDAO : " + ex.getMessage());
        	log.error("Sql: " + sql);
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return objeto;
	}
	
	/**
	 * Busca uma lista de objetos do tipo da classe passada no parâmetro podendo usar um atributo para ordenação,
	 * ou null para nenhuma ordenação.
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodos(Class<T> clazz, String ordenacao) throws BaseException {
		List<T> resultado = null;
		try {
			StringBuilder hql = new StringBuilder("select obj from ");
			hql.append(clazz.getSimpleName());
			hql.append(" obj ");
			if(ordenacao != null && !ordenacao.equals("")){
				hql.append("order by obj.");
				hql.append(ordenacao);
			}
			Query query = getEntityManager().createQuery(hql.toString());
            resultado = query.getResultList();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodos - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return resultado;
	}
	
	/**
	 * Faz uma busca paginada através da namedQuery da classe persistente.
	 * 
	 * @param namedQuery - NamedQuery da entidade persistente.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados.
	 * @param inicio - posição inicial da busca.
	 * @param tamanhoPagina - número de objetos que devem ser retornados na lista.
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodosPorNamedQuery(String namedQuery, Integer inicio, Integer tamanhoPagina, Object... params) 
			throws BaseException {
		
		List<T> lista = null;
		try {
			int start = (inicio - 1);
            Query query = getEntityManager().createNamedQuery(namedQuery.trim());
            query.setFirstResult(start);
            query.setMaxResults(tamanhoPagina);
            JPAUtil.setParameters(query, params);
            lista = query.getResultList();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodosNamedQuery - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return lista;
	}
	
	/**
	 * Recupera uma lista de objetos do banco através da namedQuery declarada no objeto persistente
	 * 
	 * @param namedQuery - NamedQuery da entidade persistente
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodosPorNamedQuery(String namedQuery, Object... params)
			throws BaseException {
		
		List<T> lista = null;
		try {
			Query query = getEntityManager().createNamedQuery(namedQuery);
            JPAUtil.setParameters(query, params);
            lista = query.getResultList();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodosNamedQuery - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return lista;
	}

	/**
	 * Recupera uma lista de objetos do banco através de native query.
	 * 
	 * @param clazz - Classe que representa os dados do banco.
	 * @param sql - sql nativo.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados.
	 * @param inicio - posição inicial da busca.
	 * @param tamanhoPagina - número de objetos que devem ser retornados na lista.
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodosPorNativeQuery(Class<T> clazz, String sql, Integer inicio, Integer tamanhoPagina, Object... params)
			throws BaseException {
		
		List<T> lista = null;
		try {
			int start = (inicio - 1);
            Query query = getEntityManager().createNativeQuery(sql, clazz);
            query.setFirstResult(start);
            query.setMaxResults(tamanhoPagina);
            if (params != null) {
                JPAUtil.setParameters(query, params);
            }
            lista = query.getResultList();
        
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodosNativeQuery - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
	    return lista;
	}

	/**
	 * Recupera uma lista de objetos do banco através de native query.
	 * 
	 * @param clazz - Classe que representa os dados do banco.
	 * @param sql - sql nativo.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta,
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodosPorNativeQuery(Class<T> clazz,String sql, Object... params) 
			throws BaseException {
		
		List<T> lista = null;
		try {
		    Query query = getEntityManager().createNativeQuery(sql, clazz);
            if (params != null) {
            	JPAUtil.setParameters(query, params);
            }
            lista = query.getResultList();
	    
		}catch(NoResultException e){
                        return null;
		} catch (Exception ex) {
			log.error("Erro ao buscarTodosNativeQuery - SefazDAO : " + ex.getMessage());
			throw new BaseException(ex, "sefaz.erro.persistencia.generico");
		}
	    return lista;
	}
	
	/**
	 * Recupera uma lista de objetos do banco através de native query.
	 * 
	 * @param sql - sql nativo.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta,
	 * @param nomeImplicito - Nome do resultSetMapping representando o mapeamento das colunas para
	 * as propriedades da classe.
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodosPorNativeQuery(String sql, String nomeImplicito, Object... params) 
			throws BaseException {
		
		List<T> ret = null;
		try {
		    Query query = getEntityManager().createNativeQuery(sql, nomeImplicito);
            JPAUtil.setParameters(query, params);
            ret = query.getResultList();
        
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodosNativeQuery - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
	    return ret;
	}

	/**
	 * Recupera uma lista de objetos do banco através de native query.
	 * 
	 * @param sql - sql nativo.
	 * @param params - Array de objetos contendo os parâmetros usados na consulta, 
	 * são utilizados na ordem em que são passados.
	 *  
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<T> buscarTodosPorNativeQuery(String sql, Object... params) throws BaseException {
		List<T> lista = null;
		try {
			Query query = getEntityManager().createNativeQuery(sql);
            if (params != null) {
                JPAUtil.setParameters(query, params);
            }
            lista = query.getResultList();
            
        }catch(NoResultException e){
                return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodosNativeQuery - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return lista;
	}

	/**
	 * Busca objeto com base na API JPAParams
	 * 
	 */
	@Override
	public T buscarEntidade(IJPAParams<T> params) throws BaseException {
		T objeto = null;
		try{
			if (params.isNativeQuery()) {
				objeto = buscarPorNativeQuery(params.getClassePersistente(), params.getSql(),
	                    params.getParams()); 
	        } else {
	        	objeto = buscarPorNamedQuery(params.getSql(), params.getParams());
	        }
		}catch(NoResultException e){
			return null;
		}catch (Exception e) {
			log.error("Erro ao buscarEntidade - SefazDAO : " + e.getMessage());
			throw new BaseException(e, "sefaz.erro.persistencia.generico");
		}
		return objeto;
	}

	/**
	 * Busca lista de objetos com base na API JPAParams
	 */
	@Override
	public List<T> buscarTodos(IJPAParams<T> params) throws BaseException {
		List<T> lista = null;
		try{
			if (params.isNativeQuery()) {
				if (params.isPaginado()) {
					lista = buscarTodosPorNativeQuery(params.getClassePersistente(),
		               		params.getSql(),
		               		params.getParams(),
		               		params.getPaginaAtual(),
		               		params.getTamanhoPagina());
				} else {
		        	if (params.getClassePersistente() != null) {
		        		lista = buscarTodosPorNativeQuery(params.getClassePersistente(), 
		                 		params.getSql(), 
		                   		params.getParams());
		             } else {
		            	 lista = buscarTodosPorNamedQuery(params.getSql(), params.getParams());
		             }
		        }
	
			} else {
	
				if (params.isPaginado()) {
					lista = buscarTodosPorNamedQuery(params.getSql(),
		               		params.getParams(),
		               		params.getPaginaAtual(),
		               		params.getTamanhoPagina());
				} else {
					lista = buscarTodosPorNamedQuery(params.getSql(),
							params.getParams());
				}
			}
		}catch(NoResultException e){
			return null;
		}catch (Exception e) {
			log.error("Erro ao buscarTodos - SefazDAO : " + e.getMessage());
			throw new BaseException(e, "sefaz.erro.persistencia.generico");
		}
		return lista;
	}
	
	/**
	 * Executa as named querys referentes a verificação de inclusão ou alteração
	 * de atributos que não podem se repetir
	 * 
	 * entidade : classe persistente
	 * modo : "G" para gravação(inclusão) e "E" para edição
	 * 
	 * @author gaspar
	 */
	public void naoDeveExistir(T entidade, String modo) throws BaseException {
		try{
			List<String> querys = AnotacaoUtil.getNamedQuerysNaoDeveExistir(entidade.getClass());
			if(!ColecaoUtil.ehNuloOuVazio(querys)){
				for (String namedQuery : querys) {
					//recupera o nome do atributo
					int tamanho = (entidade.getClass().getSimpleName() + ".naoDeveExistir").length();
					String atributo = namedQuery.substring(tamanho);
					//atributo = HelperString.normalizar(atributo);
					
					Object valorAtributo = ReflexaoUtil.executaMetodo(
							ReflexaoUtil.getMetodo(entidade, "get" + atributo), 
							entidade);
					
					if(valorAtributo == null || StringUtil.ehBrancoOuNulo(valorAtributo.toString())){
						return;
					}
					
					String query = AnotacaoUtil.getQueryDeNamedQuery(namedQuery, entidade.getClass());
					
					//faz tratamento para exclusão lógica
					if(entidade.getClass().getAnnotation(ExclusaoLogica.class) != null){
						query += " and obj.ativo = true";
					}
					
					//faz tratamento para edição
					if(modo.equals("E")){
						query += " and obj.id <> " + entidade.getId().toString();
					}
					
					Query qry = getEntityManager().createQuery(query);
					qry.setParameter("p0", valorAtributo);
					
					Long resultado = (Long) qry.getSingleResult();
					if(resultado >= 1){
						log.error("Erro naoDeveExistir - SefazDAO : Já existe um registro com esse valor");
						throw new BaseException("Já existe um registro com esse(a) " + atributo);
						//throw new BaseException("sefaz.validacao."+namedQuery);
					}
				}
			}
		}catch(Exception e){
			//Se for BaseException somente disapara o erro para frente
			if(e instanceof BaseException){
				BaseException se = (BaseException) e;
				throw se;
			}
			log.error("Erro naoDeveExistir - SefazDAO : " + e.getMessage());
			throw new BaseException(e, "Erro ao executar naoDeveExistir");
			
		}
	}
	
	/**
	 * Executa o count conforme a classe passada no parâmetro
	 * @param clazz - classe persistente
	 * @return
	 * @throws BaseException
	 * 
	 * @author gaspar
	 */
	public Long buscarCount(Class<T> clazz) throws BaseException{
		Long count = null;
		StringBuilder hql = null;
		try {
			hql = new StringBuilder();
			hql.append("select count(obj) from ");
			hql.append(clazz.getSimpleName());
			hql.append(" obj ");
			
			Query query = getEntityManager().createQuery(hql.toString());
			count = (Long) query.getSingleResult();
			
			hql = null;
		}catch(NoResultException e){
			return null;
		}catch (Exception ex) {
	    	log.error("Erro ao buscarCount - SefazDAO : " + ex.getMessage());
	    	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
	    }
		return count;
	}
	
	
	/**
	 * Busca todos os objetos da classe usando paginação
	 * @param clazz - classe persistente
	 * @param ordenacao - atributo usado na ordenação dos resultados
	 * @param inicio - posição inicial da busca.
	 * @param tamanhoPagina - número de objetos que devem ser retornados na lista.
	 * @return
	 * @throws BaseException
	 * 
	 * @author gaspar
	 */
	@SuppressWarnings("unchecked")
	public List<T> buscarTodos(Class<T> clazz, String ordenacao, Integer inicio, Integer tamanhoPagina) throws BaseException {
		List<T> resultado = null;
		try {
			StringBuilder hql = new StringBuilder("select obj from ");
			hql.append(clazz.getSimpleName());
			hql.append(" obj ");
			if(ordenacao != null && !ordenacao.equals("")){
				hql.append("order by obj.");
				hql.append(ordenacao);
			}
			Query query = getEntityManager().createQuery(hql.toString());
			query.setFirstResult(inicio);
			query.setMaxResults(tamanhoPagina);
            resultado = query.getResultList();
            
        }catch(NoResultException e){
        	return null;
        } catch (Exception ex) {
        	log.error("Erro ao buscarTodos - SefazDAO : " + ex.getMessage());
        	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
        }
		return resultado;
	}
	
	/**
	 * Busca através de uma namedQuery que faz um count na tabela e devolve o resultado do count
	 * @param namedQuery
	 * @param params
	 * @return
	 * @throws BaseException
	 */
	public Object buscarCount(String namedQuery, Object... params) throws BaseException {
		Object resultado = null;
		try {
			Query query = getEntityManager().createNamedQuery(namedQuery);
			JPAUtil.setParameters(query, params);
			resultado = query.getSingleResult();
			
		}catch (NoResultException e) {
			log.debug("Objeto não encontrado! - - SefazDAO");
			return null;
		} catch (Exception ex) {
	    	log.error("Erro ao buscarCount - SefazDAO : " + ex.getMessage());
	    	throw new BaseException(ex, "sefaz.erro.persistencia.generico");
	    }
		return resultado;
	}
	
}
